﻿using System.Collections.Generic;
using System.Linq;
using Baula.TextGen.Framework.Sections;
using Baula.TextGen.Framework.Tools;

namespace Baula.TextGen.Framework
{
    public class Document
    {
        private readonly List<Part> _parts = new List<Part>();
        private readonly Part _mainPart;

        public Document(DocumentTemplate documentTemplate)
        {
            _mainPart = documentTemplate.MainPartTemplate.CreatePart();
        }

        protected internal ValuesForPlaceholders ValuesForPlaceholders
        {
            get { return MainPart.ValuesForPlaceholders; }
        }

        public List<Part> Parts
        {
            get { return _parts; }
        }

        private Part MainPart
        {
            get { return _mainPart; }
        }

        public string RenderToString(RenderMode renderMode = RenderMode.Heading)
        {
            var lineCollector = new LineCollector();

            SetupRelocationSections();

            var renderedMainPart = RenderMainPartTemplate(renderMode);
            if (!string.IsNullOrEmpty(renderedMainPart))
            {
                lineCollector.AppendAsNewLine(renderedMainPart);
            }

            foreach (var part in Parts)
            {
                var renderedPart = part.RenderToString(renderMode);
                if (!string.IsNullOrEmpty(renderedPart))
                {
                    lineCollector.AppendAsNewLine(renderedPart);
                }
            }

            return lineCollector.ToString();
        }

        private void SetupRelocationSections()
        {
            foreach (var part in Parts)
            {
                foreach (var relocationSection in part.PartTemplate.Sections.OfType<RelocationSection>())
                {
                    SetupRelocationSection(relocationSection);
                }
            }
        }

        private void SetupRelocationSection(RelocationSection relocationSection)
        {
            var foundPlaceholderSection = GetPlaceholderSection(relocationSection.TargetSectionName);
            if (foundPlaceholderSection == null)
            {
                throw new UnknownPlaceholderSectionException(relocationSection.TargetSectionName);
            }
            relocationSection.RelocateTo = foundPlaceholderSection;
        }

        private PlaceholderSection GetPlaceholderSection(string targetSectionName)
        {
            return MainPart.PartTemplate.PlaceholderSections.Values.FirstOrDefault(ps => ps.Name == targetSectionName);
        }

        private string RenderMainPartTemplate(RenderMode renderMode)
        {
            foreach (var part in Parts)
            {
                foreach (var relocationSection in part.PartTemplate.Sections.OfType<RelocationSection>())
                {
                    MainPart.AppendToPlaceholderSection(relocationSection, part);
                }
            }

            return MainPart.RenderToString(renderMode);
        }
    }
}